////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include "CircleHullHandler.hpp"

#include <SmegLight/Hull/CircleHull.hpp>

#include <SmegLight/Light/LightSystem.hpp>

#include "../../tinyxml2/tinyxml2.h"
#include "../../Canvas/SmegEditorCanvas.hpp"

////////////////////////////////////////////////////////////
/// Constructor
////////////////////////////////////////////////////////////
CircleHullHandler::CircleHullHandler() :
    QuadTreeOccupantHandler()
{
}

////////////////////////////////////////////////////////////
/// Copy Constructor
////////////////////////////////////////////////////////////
CircleHullHandler::CircleHullHandler( const CircleHullHandler& _Copy ) :
    QuadTreeOccupantHandler( _Copy )
{
}

////////////////////////////////////////////////////////////
/// Init the handler and setup the properties
/// QuadTreeOccupantHandler::InitFromGrid need to be called AFTER the specialized class
////////////////////////////////////////////////////////////
bool CircleHullHandler::InitFromGrid( wxPropertyGrid* _pPropertyGrid ) {
    // Radius
    wxPGProperty* pCurProp = _pPropertyGrid->GetProperty("Radius");
    sf::Vector2f newRadius(
            pCurProp->GetPropertyByName("x")->GetValue().GetAny().As<float>(),
            pCurProp->GetPropertyByName("y")->GetValue().GetAny().As<float>()
            );

    // Num Vertices
    pCurProp = _pPropertyGrid->GetProperty("Num Vertices");
    wxAny numVerticesValue = pCurProp->GetValue();

    // Angle will be set in BaseObjectHandler::Init, that is why we need to call it at the END
    m_pObject = new smeg::light::CircleHull( newRadius,
                                            (unsigned)numVerticesValue.As<long>() );

    return QuadTreeOccupantHandler::InitFromGrid( _pPropertyGrid );
}
    
////////////////////////////////////////////////////////////
/// Init the handler from an XMLElement
/// QuadTreeOccupantHandler::InitFromXML need to be called AFTER the specialized class
////////////////////////////////////////////////////////////
bool CircleHullHandler::InitFromXML( tinyxml2::XMLElement* _pElement, const wxString& _ProjectPath ) {
    // Get the infos
    tinyxml2::XMLElement* paramElem = _pElement->FirstChildElement( "Param" );

    m_pObject = new smeg::light::CircleHull();
    smeg::light::CircleHull* circleHullObj = static_cast< smeg::light::CircleHull* >( m_pObject );

    if ( QuadTreeOccupantHandler::InitFromXML( _pElement, _ProjectPath ) ) {
        while ( paramElem ) {
            wxString paramName = paramElem->Attribute( "name" );

            if ( "Radius" == paramName ) {
                // Radius
                circleHullObj->SetRadius( sf::Vector2f( paramElem->FloatAttribute( "x" ), paramElem->FloatAttribute( "y" ) ) );
            } else if ( "Num Vertices" == paramName ) {
                // Num Vertices
                circleHullObj->SetNumVertices( paramElem->UnsignedAttribute( "value" ) );
            }

            paramElem = paramElem->NextSiblingElement( "Param" );
        }
    } else {
        smeg::light::LightSystem::GetInstance()->RemoveHull( circleHullObj );
        m_pObject = NULL;
        return false;
    }

    return true;
}
    
////////////////////////////////////////////////////////////
/// Add the created object to the scene
////////////////////////////////////////////////////////////
void CircleHullHandler::AddObjectToScene() {
    smeg::light::LightSystem::GetInstance()->AddHull( static_cast< smeg::light::CircleHull* >( m_pObject ) );
}
    
////////////////////////////////////////////////////////////
/// Remove the created object from the scene
////////////////////////////////////////////////////////////
void CircleHullHandler::RemoveObjectFromScene( bool _bDeleteObject ) {
    smeg::light::LightSystem::GetInstance()->RemoveHull( static_cast< smeg::light::CircleHull* >( m_pObject ), _bDeleteObject );
    if ( _bDeleteObject ) {
        m_pObject = NULL;
    }
}
    
////////////////////////////////////////////////////////////
/// Return the value of a property
////////////////////////////////////////////////////////////
wxString CircleHullHandler::GetValueAsString( const wxString& _PropertyName ) const {
    smeg::light::CircleHull * circleHullObj = static_cast< smeg::light::CircleHull* >( m_pObject );

    if ( "Radius.x" == _PropertyName ) {
        return wxString::Format( "%f", circleHullObj->GetRadius().x );
    } else if ( "Radius.y" == _PropertyName ) {
        return wxString::Format( "%f", circleHullObj->GetRadius().y );
    } else if ( "Num Vertices" == _PropertyName ) {
        return wxString::Format( "%d", circleHullObj->GetNumVertices() );
    } else {
        return QuadTreeOccupantHandler::GetValueAsString( _PropertyName );
    }
}
    
////////////////////////////////////////////////////////////
/// Handle the change of a property and apply it to the object
////////////////////////////////////////////////////////////
bool CircleHullHandler::OnPropertyChanged( wxPropertyGrid* _pPropertyGrid, wxPGProperty* _pChangedProperty ) {
    if ( QuadTreeOccupantHandler::OnPropertyChanged( _pPropertyGrid, _pChangedProperty ) ) {
        return true;
    }

    smeg::light::CircleHull * circleHullObj = static_cast< smeg::light::CircleHull* >( m_pObject );
    
    // Handle changes in values, as needed
    const wxString& propName(_pChangedProperty->GetName());
    if ( "Radius" == propName || "Radius" == propName.BeforeFirst( '.' ) ) {
        _pChangedProperty = _pPropertyGrid->GetProperty( "Radius" );
        sf::Vector2f newRadius = sf::Vector2f(
            _pChangedProperty->GetPropertyByName("x")->GetValue().GetAny().As<float>(),
            _pChangedProperty->GetPropertyByName("y")->GetValue().GetAny().As<float>()
            );

        circleHullObj->SetRadius( newRadius );
    } else if ( "Num Vertices" == propName ) {
        wxAny numVerticesValue = _pChangedProperty->GetValue();
        circleHullObj->SetNumVertices( (unsigned)numVerticesValue.As<long>() );
    } else {
        return false;
    }

    return true;
}
   
////////////////////////////////////////////////////////////
/// Create an XML string with the value of the object
////////////////////////////////////////////////////////////
wxString CircleHullHandler::InnerXMLString( const wxString& _ProjectPath, const wxString& _Tab ) const {
    smeg::light::CircleHull * circleHullObj = static_cast< smeg::light::CircleHull* >( m_pObject );

    return QuadTreeOccupantHandler::InnerXMLString( _ProjectPath, _Tab ) +
        _Tab + wxT( "<Param name=\"Radius\" x=\"" ) + wxString::Format( "%f", circleHullObj->GetRadius().x ) + wxT( "\" y=\"" ) + wxString::Format( "%f", circleHullObj->GetRadius().y ) + wxT( "\" />\n" ) +
        _Tab + wxT( "<Param name=\"Num Vertices\" value=\"" ) + wxString::Format( "%d", circleHullObj->GetNumVertices() ) + wxT( "\" />\n" );
}